<html><head><meta charset="utf-8"/><title>MVVM</title></head><body><h1>MVVM</h1><div class="x-wiki-content x-main-content">
 <p>
  什么是MVVM？
  <a href="https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel">
   MVVM
  </a>
  是Model-View-ViewModel的缩写。
 </p>
 <p>
  要编写可维护的前端代码绝非易事。我们已经用MVC模式通过koa实现了后端数据、模板页面和控制器的分离，但是，对于前端来说，还不够。
 </p>
 <p>
  这里有童鞋会问，不是讲Node后端开发吗？怎么又回到前端开发了？
 </p>
 <p>
  对于一个全栈开发工程师来说，懂前端才会开发出更好的后端程序（不懂前端的后端工程师会设计出非常难用的API），懂后端才会开发出更好的前端程序。程序设计的基本思想在前后端都是通用的，两者并无本质的区别。这和“不想当厨子的裁缝不是好司机”是一个道理。
 </p>
 <p>
  当我们用Node.js有了一整套后端开发模型后，我们对前端开发也会有新的认识。由于前端开发混合了HTML、CSS和JavaScript，而且页面众多，所以，代码的组织和维护难度其实更加复杂，这就是MVVM出现的原因。
 </p>
 <p>
  在了解MVVM之前，我们先回顾一下前端发展的历史。
 </p>
 <p>
  在上个世纪的1989年，欧洲核子研究中心的物理学家Tim Berners-Lee发明了超文本标记语言（HyperText Markup Language），简称HTML，并在1993年成为互联网草案。从此，互联网开始迅速商业化，诞生了一大批商业网站。
 </p>
 <p>
  最早的HTML页面是完全静态的网页，它们是预先编写好的存放在Web服务器上的html文件。浏览器请求某个URL时，Web服务器把对应的html文件扔给浏览器，就可以显示html文件的内容了。
 </p>
 <p>
  如果要针对不同的用户显示不同的页面，显然不可能给成千上万的用户准备好成千上万的不同的html文件，所以，服务器就需要针对不同的用户，动态生成不同的html文件。一个最直接的想法就是利用C、C++这些编程语言，直接向浏览器输出拼接后的字符串。这种技术被称为CGI：Common Gateway Interface。
 </p>
 <p>
  很显然，像新浪首页这样的复杂的HTML是不可能通过拼字符串得到的。于是，人们又发现，其实拼字符串的时候，大多数字符串都是HTML片段，是不变的，变化的只有少数和用户相关的数据，所以，又出现了新的创建动态HTML的方式：ASP、JSP和PHP——分别由微软、SUN和开源社区开发。
 </p>
 <p>
  在ASP中，一个asp文件就是一个HTML，但是，需要替换的变量用特殊的
  <code>
   &lt;%=var%&gt;
  </code>
  标记出来了，再配合循环、条件判断，创建动态HTML就比CGI要容易得多。
 </p>
 <p>
  但是，一旦浏览器显示了一个HTML页面，要更新页面内容，唯一的方法就是重新向服务器获取一份新的HTML内容。如果浏览器想要自己修改HTML页面的内容，就需要等到1995年年底，JavaScript被引入到浏览器。
 </p>
 <p>
  有了JavaScript后，浏览器就可以运行JavaScript，然后，对页面进行一些修改。JavaScript还可以通过修改HTML的DOM结构和CSS来实现一些动画效果，而这些功能没法通过服务器完成，必须在浏览器实现。
 </p>
 <p>
  用JavaScript在浏览器中操作HTML，经历了若干发展阶段：
 </p>
 <p>
  第一阶段，直接用JavaScript操作DOM节点，使用浏览器提供的原生API：
 </p>
 <pre><code>var dom = document.getElementById('name');
dom.innerHTML = 'Homer';
dom.style.color = 'red';
</code></pre>
 <p>
  第二阶段，由于原生API不好用，还要考虑浏览器兼容性，jQuery横空出世，以简洁的API迅速俘获了前端开发者的芳心：
 </p>
 <pre><code>$('#name').text('Homer').css('color', 'red');
</code></pre>
 <p>
  第三阶段，MVC模式，需要服务器端配合，JavaScript可以在前端修改服务器渲染后的数据。
 </p>
 <p>
  现在，随着前端页面越来越复杂，用户对于交互性要求也越来越高，想要写出Gmail这样的页面，仅仅用jQuery是远远不够的。MVVM模型应运而生。
 </p>
 <p>
  MVVM最早由微软提出来，它借鉴了桌面应用程序的MVC思想，在前端页面中，把Model用纯JavaScript对象表示，View负责显示，两者做到了最大限度的分离。
 </p>
 <p>
  把Model和View关联起来的就是ViewModel。ViewModel负责把Model的数据同步到View显示出来，还负责把View的修改同步回Model。
 </p>
 <p>
  ViewModel如何编写？需要用JavaScript编写一个通用的ViewModel，这样，就可以复用整个MVVM模型了。
 </p>
 <p>
  一个MVVM框架和jQuery操作DOM相比有什么区别？
 </p>
 <p>
  我们先看用jQuery实现的修改两个DOM节点的例子：
 </p>
 <pre><code>&lt;!-- HTML --&gt;
&lt;p&gt;Hello, &lt;span id="name"&gt;Bart&lt;/span&gt;!&lt;/p&gt;
&lt;p&gt;You are &lt;span id="age"&gt;12&lt;/span&gt;.&lt;/p&gt;
</code></pre>
 <div class="uk-panel">
  <p>
   Hello,
   <span class="uk-text-bold uk-text-danger" id="name">
    Bart
   </span>
   !
  </p>
  <p>
   You are
   <span class="uk-text-bold uk-text-danger" id="age">
    12
   </span>
   .
  </p>
 </div>
 <p>
  用jQuery修改name和age节点的内容：
 </p>
 <pre><code class="language-x-javascript">'use strict';
----
var name = 'Homer';
var age = 51;

$('#name').text(name);
$('#age').text(age);
----
// 执行代码并观察页面变化
</code></pre>
 <p>
  如果我们使用MVVM框架来实现同样的功能，我们首先并不关心DOM的结构，而是关心数据如何存储。最简单的数据存储方式是使用JavaScript对象：
 </p>
 <pre><code>var person = {
    name: 'Bart',
    age: 12
};
</code></pre>
 <p>
  我们把变量
  <code>
   person
  </code>
  看作Model，把HTML某些DOM节点看作View，并假定它们之间被关联起来了。
 </p>
 <p>
  要把显示的name从
  <code>
   Bart
  </code>
  改为
  <code>
   Homer
  </code>
  ，把显示的age从
  <code>
   12
  </code>
  改为
  <code>
   51
  </code>
  ，我们并不操作DOM，而是直接修改JavaScript对象：
 </p>
 <div class="uk-panel" id="vm-person">
  <p>
   Hello,
   <span class="uk-text-bold uk-text-danger" v-text="name">
   </span>
   !
  </p>
  <p>
   You are
   <span class="uk-text-bold uk-text-danger" v-text="age">
   </span>
   .
  </p>
 </div>
 <script src="https://unpkg.com/vue@2.0.1/dist/vue.js">
 </script>
 <script>
  var person = {
    name: 'Bart',
    age: 12
};
var app = new Vue({
    el: '#vm-person',
    data: person
});
window.person = person;
 </script>
 <pre><code class="language-x-javascript">'use strict';
----
person.name = 'Homer';
person.age = 51;
----
// 执行代码并观察页面变化
</code></pre>
 <p>
  执行上面的代码，我们惊讶地发现，改变JavaScript对象的状态，会导致DOM结构作出对应的变化！这让我们的关注点从如何操作DOM变成了如何更新JavaScript对象的状态，而操作JavaScript对象比DOM简单多了！
 </p>
 <p>
  这就是MVVM的设计思想：关注Model的变化，让MVVM框架去自动更新DOM的状态，从而把开发者从操作DOM的繁琐步骤中解脱出来！
 </p>
</div>
</body></html>